(function($) {
    $.widget("ui.layout", {
        // These options will be used as defaults
        options: {
            layout_width: 960,
            layout_width_handle: '.layout_width',
            //selector input change layout width
            column_width_handle: '.column_fixed_width',
            //selector input set fixed width for column
            data: []
        }

        // Set up the widget
        ,
        _create: function() {
            this._default_container_html = '<div class="layout-col ui-widget ui-widget-content"><span class="ui-icon ui-icon-close ui-delete-widget-panel"></span><span class="container-panel"></span></div>';
            this._container_row_html = '<table cellspacing="0" cellpadding="0"><tr><td>' + this._default_container_html + '</td><td class="layout-add" style="width: 30px;"><div class="layout-add-col ui-widget ui-widget-content ui-state-default"><span class="ui-icon ui-icon-plusthick"></span></div></td><td class="layout-handle" style="width:30px;"><div class="layout-item-handle ui-widget ui-widget-content ui-state-default"><span class="ui-icon ui-icon-grip-dotted-vertical"></span></div></td></tr></table>';
            this._container_add_row_html = '<table class="layout-add-row" cellspacing="0" cellpadding="0"><tr><td><div class="layout-add-colrow ui-widget ui-widget-content ui-state-default"><span class="ui-icon ui-icon-plusthick"></span></div></td></tr></table>';
            this.element.addClass('ui-layout').width(this.options.layout_width + 64).append($(this._container_row_html)).append($(this._container_add_row_html)).delegate('.layout-add-colrow', 'click', $.proxy(this.add_row, this)).delegate('.layout-add-col', 'click', $.proxy(this.add_column, this)).delegate('.ui-icon-close', 'click', $.proxy(this.remove_column, this)).delegate('.layout-col', 'click', $.proxy(this.select_column, this));

            $('body').delegate(this.options.layout_width_handle, 'change', $.proxy(this.layout_width_change, this));
            $('body').delegate(this.options.column_width_handle, 'change', $.proxy(this.column_width_change, this));
            $('body').delegate(this.options.column_width_handle, 'focus', function() {
                this.select();
            });
            this.refresh();

            if (this.options.data.length) {
                var row_obj = null;
                for (var i = 0; i < this.options.data.length; i++) {
                    if (i == 0) row_obj = this.element.find('table:first');
                    else {
                        this.element.find('.layout-add-colrow').trigger('click');
                        row_obj = this.element.find('.layout-add-row').prev();
                    }
                    if (this.options.data[i].length) {
                        for (var j = 0; j < this.options.data[i].length; j++) {
                            if (j == 0) {
                                $('td:first', row_obj).find('.container-panel').text(this.options.data[i][j]);
                            }
                            else {
                                $('.layout-add-col', row_obj).trigger('click');
                                var column = $('td:eq(' + j + ')', row_obj);
                                this.resize_column(column, parseInt(this.options.data[i][j]));
                            }
                        }
                        this.resize_column($('td:first', row_obj), parseInt(this.options.data[i][0]));
                    }
                }
            }
            else {
                this.element.find('table:first td:first .container-panel').text(this.options.layout_width);
            }
        }

        ,
        destroy: function() {
            this.element.undelegate('.layout-add-colrow', 'click').undelegate('.layout-add-col', 'click').undelegate('.ui-icon-close', 'click').undelegate('.layout-col', 'click').html('');

            $('body').undelegate(this.options.layout_width_handle, 'change');
            $('body').undelegate(this.options.column_width_handle, 'change');
            $('body').undelegate(this.options.column_width_handle, 'focus');
            $.Widget.prototype.destroy.call(this);
        }

        ,
        refresh: function() {
            //init resize
            this.element.find('.layout-col').resizable('destroy').resizable({
                minHeight: 50,
                maxHeight: 50,
                minWidth: 30,
                resize: $.proxy(function(event, ui) {
                    var column = ui.element.closest('td');
                    this.resize_column(column, column.find('.layout-col').width() + 2);
                }, this)
            });
            //init sort row
            this.element.sortable('destroy').sortable({
                cancel: '.disabled',
                placeholder: 'ui-state-highlight',
                handle: '.layout-item-handle'
            });
            this.deselect_column();
        }

        //add col
        ,
        add_column: function(event) {
            var column = null,
                new_column_width = 0;
            if ($(this._column_selected).size()) {
                new_column_width = Math.round(this._column_selected.width() / 2);
                this._column_selected.width(new_column_width);
                this._column_selected.before('<td>' + this._default_container_html + '</td>');
                column = this._column_selected.prev();
            }
            else {
                var column_prev = $(event.target).closest('td').prev();
                new_column_width = Math.round(column_prev.width() / 2);
                column_prev.width(new_column_width);
                column_prev.before('<td>' + this._default_container_html + '</td>');
                column = $(event.target).closest('td').prev();
            }
            this.resize_column(column, new_column_width);
            this.refresh();
            return false;
        }

        //add col
        ,
        resize_column: function(column, width) {
            element = $(column).find('.layout-col');
            element.width(width - 2);
            var column_resize = column.next();
            if (column_resize.size() <= 0 || column_resize.hasClass('layout-add')) {
                column_resize = column.prevAll().last();
                if (column_resize.size() <= 0) {
                    column.width(this.options.layout_width).find('.layout-col').width(this.options.layout_width - 2).find('.container-panel').text(this.options.layout_width);
                    return false;
                }
            }
            var ow = this.options.layout_width - width;
            column.siblings().each(function(index) {
                if ($(this).get(0) != column_resize.get(0) && $(this).get(0) != column.get(0) && $(this).hasClass('layout-add') === false && $(this).hasClass('layout-handle') === false) {
                    ow = ow - $(this).width();
                    $(this).find('.container-panel').text($(this).width());
                }
            });
            column.width(width).find('.container-panel').text(width);
            column_resize.width(ow).find('.layout-col').width(ow - 2).find('.container-panel').text(ow);
        }

        ,
        remove_column: function(event) {
            var column = $(event.target).closest('td');

            //remove row
            if (column.siblings('td').size() <= 2) {
                if (column.closest('table').siblings().size() > 1) column.closest('table').remove();
            }
            else
            {
                var siblings = column.siblings(':not(.layout-add,.layout-handle)');
                column.remove();
                if (siblings.size() >= 1)
                {
                    
                /*}
                else if (siblings.size() > 1)
                {*/
                    var removed_width = parseInt(column.find('.container-panel').text());
                    var width = parseInt(siblings.first().find('.container-panel').text())+removed_width;
                    this.resize_column(siblings.first(), width);
                }
            }
            return false;
        }

        //add row
        ,
        add_row: function(event) {
            $(event.target).closest('table').before(this._container_row_html);
            $(event.target).closest('table').prev().find('td:first .container-panel').text(this.options.layout_width);
            this.refresh();
            return false;
        }

        //get data
        ,
        serialize: function() {
            var rows = [];
            this.element.find('table:not(.layout-add-row)').each(function() {
                var cols = [];
                $('td:not(.layout-add,.layout-handle)', this).each(function() {
                    cols.push(parseInt($('.container-panel', this).text()));
                });
                rows.push(cols);
            });
            return rows;
        }

        ,
        select_column: function(event) {
            var fixed_width;
            this.deselect_column();
            this._column_selected = $(event.target).closest('td');
            this._column_selected.find('.layout-col').addClass('ui-state-hover');
            fixed_width = this._column_selected.find('.container-panel').text();
            $(this.options.column_width_handle).val(fixed_width).get(0).focus();
            this._trigger('selectcolumn', event, {width: fixed_width});
            return false;
        }

        ,
        deselect_column: function() {
            this._column_selected = null;
            this.element.find('.layout-col.ui-state-hover').removeClass('ui-state-hover');
        }

        ,
        layout_width_change: function(event) {
            var _this = this,
                layout_width = parseInt($(this.options.layout_width_handle).val()),
                layout_width_old = this.options.layout_width,
                rows = this.element.find('table:not(.layout-add-row)');
            if (layout_width <= 30) {
                alert('Invalid width value');
                return false;
            }
            this.options.layout_width = layout_width;
            //calculate value
            rows.each(function() {
                $(this).find('td:not(.layout-add,.layout-handle)').each(function() {
                    var width = $(this).width();
                    width = Math.round(layout_width * width / layout_width_old);
                    $(this).data('width', width);
                });
            });
            //apply GUI
            rows.each(function() {
                var cols = $(this).find('td:not(.layout-add,.layout-handle)');
                cols.each(function() {
                    var width = $(this).data('width');
                    if (cols.length == 1) width = layout_width;
                    $('.container-panel', this).text(width).closest('.layout-col').width(width - 2).closest('td').width(width);
                    if (cols.length > 1) _this.resize_column($('.container-panel', this).closest('td'), width);
                });
            });
            this.element.width(layout_width + 64);
            return false;
        }

        ,
        column_width_change: function(event) {
            var fixed_width;
            if (this._column_selected != undefined && $(this._column_selected).size() && $(this._column_selected).siblings().size() > 2) {
                fixed_width = parseInt($(event.target).val());
                //min width 1 column = 30px
                if (fixed_width > (this.options.layout_width - 30)) {
                    alert('Invalid width value');
                    return false;
                }
                else this.resize_column(this._column_selected, fixed_width);
            }
            this.deselect_column();
            //return false;
        }

        ,
        layout_reserved: function(rows) {
            $('td:not(.layout-add,.layout-handle)', rows).each(function() {
                var width = $(this).width();
                width = Math.round(this.options.layout_width * (width + 2) / (this.options.layout_width + 64));
                $('.container-panel', this).text(width);
            });
        }
    });
}(jQuery))